#include "watershed.h"

using namespace pip;
using namespace std;

int main(int argc, char **argv)
{
	cout << "\n### ### ### ### ### ENTER ### ### ### ### ###\n";
	Stopwatch sw; //to meassure duration of program
	sw.start();   

	// Store commandline args in stl container
    vector<string> args(argv, argv+argc);

	// check if help is requested
	bool help(false);
	getFlagArg(args, "-h",help);
	getFlagArg(args, "-H",help);
	getFlagArg(args, "--help",help);
	getFlagArg(args, "-help",help);

	//check if help is necessary
	if (argc < 2 || help){ // to less arguments or help requested
		cout << "USAGE: list of arguments:\n\t"       //help screen
			 << " FLAG: '-h' enables this dialog"
			 << "\n\t ARGUMENT: '-i'  input-image to compute watershed {could be <short> or <unsigned char>}."
			 << "\n\t ARGUMENT: '-m' marker-image, copy of input image with added markers of one pixel size."
			 << "\n\t ARGUMENT: '-p1' main argument.        see also '-g'"
			 << "\n\t ARGUMENT: '-p2' scale-space argument. see also '-g' for '1x'"
			 << "\n\t ARGUMENT: '-g' chose gradient & scale-space factor:"
			 << " \n\t\t '0' for no pre-processing" 
			 << " \n\t\t '1' for eroded morphological gradient. Structuring Element size 'p1'"
			 << " \n\t\t '2' for normal morphological gradient. Structuring Element size 'p1'"
			 << " \n\t\t '3' for canny-edge detection. sigma <- 'p1'"
			 << " \n\t\t       if 'p1' > 10: 'p1'%10 will be performed && the edges will be closed"
			 << " \n\t\t     [unsatisfactory results due to non-maximum-surpression]"
			 << " \n\t\t '4' for multi-scale gradient. average of calling option '1' with 1 to 'p1'"
			 << " \n\t\t     [unsatisfactory results expacted for 'p1' == 1]"
			 << " \n\t\t '1x' for gaussian-scaling of image '-i' by sigma <- ('p2'/10)"
			 << " \n\t\t      where x is one of the options above [0-4] and will done after scaling."
			 << "\n\nFurther help: see README text provided by this package or send an email to a.p.meyer@students.uu.nl"
			 << " \n\t      [this menue is optimized for a terminal-window above 100 width]"
			 << endl;
		return 4319; // code for help
		}


    // Variables to be read from the commandline
    string program, marker_name(""), inputfile("");
	int gradient(1), param1(1), param2(2);
	bool m(false); // to recogbnize given marker image
    
    // Read the arguments.
    getProgramName(args, program);
    getScalarArg(args, "-i", inputfile);
    getScalarArg(args, "-m", marker_name); // !!! the marker-image is an copy of the inputimage, but additional applied markers !!!
	getScalarArg(args, "-g", gradient);
	getScalarArg(args, "-p1", param1);
	getScalarArg(args, "-p2", param2);

	// init images
	Image<unsigned char> in_uc,marker_image_uc;
	Image<short> in,marker_image,output,marker;

	// load images
	if (!importFile(in, inputfile)){
		if(!importFile(in_uc, inputfile)){
			cout << "failed to load input image! Maybe the image path is wrong...\n";
			return 1; //wrong input
		}else{
			convertAllToShort(in_uc,in);
			cout << "image loaded.\n";
		}
	}else{cout << "image loaded.\n";}

	cout << "attempting to load markers:\n";
	if (!importFile(marker_image, marker_name)){
		if(!importFile(marker_image_uc, marker_name)){
			cout << "no markers passed! . . . \n";
		}else{
			convertAllToShort(marker_image_uc,marker_image);
			cout << "marker-image loaded.\n";
			m=true;
			marker.resize(in.dimension()); // this image will only show marker positions
			marker.fill(0);
		}
	}else{
		cout << "marker-image loaded.\n";
		m=true;
		marker.resize(in.dimension()); // this image will only show marker positions
		marker.fill(0);
	}
	

	// construct the markers from altered input image

	if(m){
		int count=0;
		for(int x=0;x<in.dim(0);++x){
			for(int y=0;y<in.dim(1);++y){
				if(in(x,y)!=marker_image(x,y)){    // if marks are found, different from input image: its a marker
					   marker(x,y)=1;
					   cout << "found the " << (++count) << "th marker.   =>  Values differ: " << in(x,y) <<" vs. "<< marker_image(x,y)<< endl; 
				}  // let the user know, how many markers are there
			}
		}
	}
	
	//applying watershed and maybe a gradient
	if(gradient < 10) // param1 > 10 uses param2 for scale space...
		applygradient(in, gradient, param1);
	else
		applygradient(in, gradient, param1, param2);
	cout << "pre-processing done.\n";
	
	if (!exportFile(in, "gradient-image.pip")) {
		 error("", "can't save gradient-image . . .");
	}
	
	//actual work
	watershed(in,output,marker);
	cout << "watershed transform computed.\n";

	//save results
	if(m){
		if (!exportFile(marker, "used_markers.pip")) {
			 error("", "can't save file . . .");
		}
	}
	if (!exportFile(output, "outcome.pip")) {
		 error("", "can't save file . . .");
	}
	cout << "\n\t" << program <<":\t all ready!\n";

	cout << endl << "\tTotal time for operations: " << sw.stop() << " \a " << endl;
	cout << "\n### ### ### ### ###  END  ### ### ### ### ###\n";
	// system("pause");    // needed if not used in commandline environment
    return 0;
}